var gamejs = require('gamejs');

/**
 * MATCH : an object representing a game.
 *
 */

/**
 * Creates a match
 *
 * @param {Number} health A number > 0 indicating the player health
 *                 [default 100]
 * @param {Number} credit A number >= 0 indicating the player resources
 *                 [default 1000]
 *
 * @throws {TypeError} When an invalid type or number are used as arguments for
 *                     health or credit
 * @contructor
 */
var Match = exports.Match = function(health, credit) {
	// Check health argument
	if (typeof health === 'undefined') {
		this.health = 100;  // Default case
	}
	else if (typeof health === 'number') {
		if (health > 0) {
			this.health = health;
		}
		else {
			throw new TypeError("Match.health must be > 0");
		}
	}
	else {
		throw new TypeError("Match.health must be a number");
	}
	// Check credit argument
	if (typeof credit === 'undefined') {
		this.credit = 1000;  // Default case
	}
	else if (typeof credit === 'number') {
		if (credit >= 0) {
			this.credit = credit;
		}
		else {
			throw new TypeError("Match.credit must be >= 0");
		}
	}
	else {
		throw new TypeError("Match.credit must be a number");
	}
	// Score starts from 0
	this.score = 0;
	
	//private variables
	this._font = new gamejs.font.Font("12px sans-serif");
	this._healthSurface = this._font.render("Health", "#ff0000");
	this._cachedCredit = -1;
	this._creditSurface = null;
	this._cachedScore = -1;
	this._scoreSurface = null;
};

/**
 * Return current map
 *
 * @return {Map|undefined} the map previously setted with setMap or undefined if
 *           the Match doesn't have a map
 */
Match.prototype.getMap = function() {
	return this.map;
};

/**
 * Set current map
 *
 * @param {Map}
 */
Match.prototype.setMap = function(map) {
	this.map = map;
};

/**
 * Return health
 *
 * @return {Number} the remaining health points
 */
Match.prototype.getHealth = function() {
	return this.health;
};

/**
 * Decrease health
 *
 * @param {undefined|number} hitpoint Removes one health point if undefined
 *                          or the specified amount
 *
 * @return {number} The remaining health points (0 if dead)
 */
Match.prototype.decreaseHealth = function(hitpoint) {
	// Called without the hitpoint argument
	if (arguments.length === 0) {
		hitpoint = 1;
	}
	if (hitpoint >= this.health) {
		this.health = 0;
	}
	else {
		this.health = this.health - hitpoint;
	}
	return this.health;
};

/**
 * Return credit
 *
 * @return {Number} the player credits
 */
Match.prototype.getCredit = function() {
	return this.credit;
};

/**
 * Change credit amount
 *
 * @param {number|undefined} amount change credit by amount or increment by 1
 * if undefined
 *
 * @return {number} The remaining credit points
 *
 * @throws {RangeError} If the resulting credit after the change is < 0
 */
Match.prototype.changeCredit = function(amount) {
	// Called without the amount argument
	if (arguments.length === 0) {
		amount = 1;
	}
	// Check if the new credit value is acceptable
	var new_credit = this.credit + amount;
	if (new_credit < 0) {
		throw new RangeError("Negative credit not allowed");
	}
	else {
		this.credit = new_credit;
		return this.credit;
	}
};

/**
 * Return current player score
 *
 * @return {Number} the player score
 */
Match.prototype.getScore = function() {
	return this.score;
};

/**
 * Change score amount
 *
 * @param {undefined|number} amount change score by amount or increment by 1
 * if undefined
 *
 * @throws {RangeError} If the resulting score after the change is < 0
 *
 * @return {number} The remaining score points
 */
Match.prototype.changeScore = function(amount) {
	// Called without the amount argument
	if (arguments.length === 0) {
		amount = 1;
	}
	// Check if the new credit value is acceptable
	var new_score = this.score + amount;
	if (new_score < 0) {
		throw new RangeError("Negative credit not allowed");
	}
	else {
		this.score = new_score;
		return this.score;
	}
};

/**
 * Update the data in the game
 */
Match.prototype.update = function() {};

/**
 * Draw the overlay information
 *
 * @param {gamejs.surface} where to draw
 */
Match.prototype.draw = function(surface) {
	if(this._cachedCredit != this.credit){
		this._cachedCredit = this.credit;
		this._creditSurface = this._font.render(
			"Credit: " + this.credit, "#eeeeee"
		);
	}
	if(this._cachedScore != this.score){
		this._cachedScore = this.score;
		this._scoreSurface = this._font.render(
			"Score: " + this.score, "#eeeeee"
		);
	}
	//draw health bar
	surface.blit(this._healthSurface, [5, 5]);
	var healthBar = new gamejs.Rect(45, 8, this.health, 5);
	gamejs.draw.rect(surface, "#ff0000", healthBar, 0);
	//draw credit counter
	surface.blit(this._creditSurface, [340, 5]);
	//draw points counter
	surface.blit(this._scoreSurface, [680, 5]);
};